/**
 * 
 */
package spatial.geometry;

import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.HashSet;


/**
 * This class helps maintain k sets of intersection points. This permits
 * intersections with level 0<= level <= highest level
 * 
 * @author wu wei
 * 
 */
public class IntersectionsIndexByLevel {
	private int levelLimit;
	ArrayList<HashSet<LeveledIntersection>> leveledSets;

	/**
	 * Note that the given highest level is permitted. That is, this initiated
	 * object permits intersections with level 0<= level <= highest level.
	 * 
	 * @param highestLevel
	 */
	public IntersectionsIndexByLevel(int highestLevel) {
		this.levelLimit = highestLevel;
		this.leveledSets = new ArrayList<HashSet<LeveledIntersection>>();
		for (int i = 0; i <= this.levelLimit; i++) {
			this.leveledSets.add(new HashSet<LeveledIntersection>());
		}
	}

	public void add(LeveledIntersection wip) {
		this.checkLevel(wip.getLevel());
		this.leveledSets.get(wip.getLevel()).add(wip);
	}

	public void remove(LeveledIntersection wip) {
		this.checkLevel(wip.getLevel());
		boolean removed = this.leveledSets.get(wip.getLevel()).remove(wip);
		if (!removed) {
			throw new IllegalArgumentException(
					"trying to remove a non-existing WIntersectionPoint");
		}
	}

	public HashSet<Point2D.Double> getLevel(int level) {
		this.checkLevel(level);
		return new HashSet<Point2D.Double>(this.leveledSets.get(level));
	}

	/**
	 * Get the intersections with their level <= the given level.
	 * 
	 * @param level
	 * @return
	 */
	public HashSet<Point2D.Double> getAtMostLevel(int level) {
		this.checkLevel(level);
		HashSet<Point2D.Double> s = new HashSet<Point2D.Double>();
		for (int i = 0; i <= level; i++) {
			s.addAll(this.leveledSets.get(i));
		}
		return s;
	}

	private void checkLevel(int level) {
		if (level > this.levelLimit) {
			throw new IllegalArgumentException(
					"The given (intersection's) level is beyond the level limit!");
		}
	}

	public int getLevelLimit() {
		return levelLimit;
	}
}
